<?php
/**
 * Class for validating input field values.
 * Especially if they are from the same entity, then their label is easily calculated as an $entityName.$fieldName
 * @author jan
 */
Class EntityValidator {

    private $entity;
    private $msg;
    private $entityName;

    public function __construct($entity, $entityName, $msg=null) {
    	if ($msg == null) {
    		$msg = Messages::instance();
    	}
        $this->entity = $entity;
        $this->entityName = $entityName;
        $this->msg = $msg;
    }

    private function fieldCode($fieldName, $labelKey=null) {
    	if ($labelKey) {
    		if (substr($labelKey, 0, 2) != 't.') {
    			return 't.' . $labelKey;
    		}
    		return $labelKey;
    	}
        return $this->entityName . '.' . $fieldName;
    }

    public function required($fieldName, $labelKey=null) {
        $value = $this->entity[$fieldName];
        $isValid = TRUE;
        $fieldLabelKey = $this->fieldCode($fieldName, $labelKey);
        if ($value) {
            if (is_array($value) && count($value) == 0) {
                $this->msg->error('error.required', $fieldLabelKey);
                $isValid = FALSE;
            }
            if (is_string($value) && valid::isWhite($value)) {
                $this->msg->error('error.required', $fieldLabelKey);
                $isValid = FALSE;
            }
        }
        else {
            if ($value == '' || is_null($value)) {
                $isValid = FALSE;
            }
        }
        if (! $isValid) {
            $this->msg->error('error.required', $fieldLabelKey);
        }
        return $isValid;
    }
    
    public function applicationLanguage($fieldName, $labelKey=null) {
    	$value = $this->entity[$fieldName];
    	if ($this->required($fieldName, $labelKey)) {
	    	$languages = Kohana::config('multi_lang.allowed_languages');
	    	if (! array_key_exists($value, $languages)) {
	    		$this->msg->error('error-invalidValue', $this->fieldCode($fieldName, $labelKey));
	    	}
    	}
    }

    public function id($fieldName, $labelKey=null) {
        $value = $this->entity[$fieldName];
        if ($this->required($fieldName, $labelKey)) {
            if (! valid::isId($value)) {
                $this->msg->error('error.invalidId', $this->fieldCode($fieldName, $labelKey));
            }
        }
    }
    
    public function idOrNull($fieldName, $labelKey=null) {
    	$value = $this->entity[$fieldName];
    	if ($value != '') {
    		if (! valid::isId($value)) {
    			$this->msg->error('error.invalidId', $this->fieldCode($fieldName, $labelKey));
    		}
    	}
    }

    public function code($fieldName, $labelKey=null) {
        $value = $this->entity[$fieldName];
        if ($this->required($fieldName, $labelKey)) {
            if (! valid::isCode($value)) {
                $this->msg->error('error.invalidId', $this->fieldCode($fieldName, $labelKey));
            }
        }
    }

    public function boolean($fieldName, $labelKey=null) {
        if ($this->required($fieldName, $labelKey)) {
            $this->booleanOrNull($fieldName, $labelKey);
        }
    }
    public function booleanOrNull($fieldName, $labelKey=null) {
        if ($this->entity[$fieldName] != '') {
            if (! valid::isSqlBoolean($this->entity[$fieldName])) {
                $this->msg->error('error.notBoolean', $this->fieldCode($fieldName, $labelKey));
            }
        }
    }

    public function date($fieldName, $labelKey=null) {
        if ($this->required($fieldName, $labelKey)) {
            if (! valid::isIsoDate($this->entity[$fieldName])) {
            	$dateFormatExample = date(Kohana::lang('dateTimeFormat.dateFormat'), 1201186905); // 2008-01-24
                $this->msg->error('error.notDate', $this->fieldCode($fieldName, $labelKey), $dateFormatExample);
            }
        }
    }

    public function dateOrNull($fieldName, $labelKey=null) {
        if ($this->entity[$fieldName]) {
            return $this->date($fieldName, $labelKey);
        }
    }

    public function time($fieldName, $labelKey=null) {
        if ($this->required($fieldName, $labelKey)) {
            if (! valid::isTime($this->entity[$fieldName])) {
            	$timeFormatExample = date(Kohana::lang('dateTimeFormat.timeFormat'), 1201186905); // 2008-01-24
                $this->msg->error('error.notTime', $this->fieldCode($fieldName, $labelKey), $timeFormatExample);
            }
        }
    }

    public function timeOrNull($fieldName, $labelKey=null) {
        if ($this->entity[$fieldName]) {
            return $this->time($fieldName, $labelKey);
        }
    }

    public function integer($fieldName, $labelKey=null) {
        if ($this->required($fieldName, $labelKey)) {
            if (! valid::isInteger($this->entity[$fieldName])) {
                $this->msg->error('error-notInteger', $this->fieldCode($fieldName, $labelKey));
            }
        }
    }

    public function integerOrNull($fieldName, $labelKey=null) {
        if ($this->entity[$fieldName]) {
            return $this->integer($fieldName, $labelKey);
        }
    }

    public function positiveInteger($fieldName, $labelKey=null) {
        if ($this->required($fieldName, $labelKey)) {
            if (! valid::isPositiveInteger($this->entity[$fieldName])) {
                $this->msg->error('error.notPositiveInteger', $this->fieldCode($fieldName, $labelKey));
            }
        }
    }

    public function decimal($fieldName, $labelKey=null) {
        if ($this->required($fieldName, $labelKey)) {
            if (! valid::isDecimal($this->entity[$fieldName])) {
                $this->msg->error('error.notDecimal', $this->fieldCode($fieldName, $labelKey));
            }
        }
    }

    public function decimalOrNull($fieldName, $labelKey=null) {
        if ($this->entity[$fieldName]) {
            return $this->decimal($fieldName, $labelKey);
        }
    }

    public function positiveDecimalOrZero($fieldName, $labelKey=null) {
        if ($this->required($fieldName, $labelKey)) {
            if (! valid::isPositiveDecimalOrZero($this->entity[$fieldName])) {
                $this->msg->error('error.notPositiveDecimalOrZero', $this->fieldCode($fieldName, $labelKey));
            }
        }
    }

    /**
     * Validates all translations of the given field as beeing required.
     */
    public function localizedText($fieldName, $labelKey=null) {
        if (! is_array($this->entity[$fieldName])) {
            $this->msg->error('error.required', $this->fieldCode($fieldName, $labelKey));
            return;
        }
        foreach ($this->entity[$fieldName] as $lang => $value) {
            if (valid::isWhite($value)) {
                $this->msg->error('error.required', $this->fieldCode($fieldName, $labelKey));
                break;
            }
        }
    }

    public function minLength($fieldName, $length, $labelKey=null) {
        if ($this->required($fieldName)) {
            if (strlen($this->entity[$fieldName]) < $length) {
                $this->msg->error('error.stringTooShort', $this->fieldCode($fieldName), $length);
            }
        }
    }
    
    public function maxLength($fieldName, $length, $labelKey=null) {
    	if ($this->required($fieldName)) {
    		if (strlen($this->entity[$fieldName]) > $length) {
    			$this->msg->error('error.stringTooLong', $this->fieldCode($fieldName), $length);
    		}
    	}
    }
}
